1 /* 2 * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 27 package javax.management.openmbean; 28 29 30 // java import 31 // 32 import java.io.InvalidObjectException; 33 import java.io.ObjectStreamException; 34 import java.math.BigDecimal; 35 import java.math.BigInteger; 36 import java.util.Date; 37 import java.util.Map; 38 import java.util.HashMap; 39 40 // jmx import 41 // 42 import javax.management.ObjectName; 43 44 45 /** 46 * The <code>SimpleType</code> class is the <i>open type</i> class whose instances describe 47 * all <i>open data</i> values which are neither arrays, 48 * nor {@link CompositeData <code>CompositeData</code>} values, 49 * nor {@link TabularData <code>TabularData</code>} values. 50 * It predefines all its possible instances as static fields, and has no public constructor. 51 * <p> 52 * Given a <code>SimpleType</code> instance describing values whose Java class name is <i>className</i>, 53 * the internal fields corresponding to the name and description of this <code>SimpleType</code> instance 54 * are also set to <i>className</i>. 55 * In other words, its methods <code>getClassName</code>, <code>getTypeName</code> and <code>getDescription</code> 56 * all return the same string value <i>className</i>. 57 * 58 * @since 1.5 59 */ 60 public final class SimpleType<T> extends OpenType<T> { 61 62 /* Serial version */ 63 static final long serialVersionUID = 2215577471957694503L; 64 65 // SimpleType instances. 66 // IF YOU ADD A SimpleType, YOU MUST UPDATE OpenType and typeArray 67 68 /** 69 * The <code>SimpleType</code> instance describing values whose 70 * Java class name is <code>java.lang.Void</code>. 71 */ 72 public static final SimpleType<Void> VOID = 73 new SimpleType<Void>(Void.class); 74 75 /** 76 * The <code>SimpleType</code> instance describing values whose 77 * Java class name is <code>java.lang.Boolean</code>. 78 */ 79 public static final SimpleType<Boolean> BOOLEAN = 80 new SimpleType<Boolean>(Boolean.class); 81 82 /** 83 * The <code>SimpleType</code> instance describing values whose 84 * Java class name is <code>java.lang.Character</code>. 85 */ 86 public static final SimpleType<Character> CHARACTER = 87 new SimpleType<Character>(Character.class); 88 89 /** 90 * The <code>SimpleType</code> instance describing values whose 91 * Java class name is <code>java.lang.Byte</code>. 92 */ 93 public static final SimpleType<Byte> BYTE = 94 new SimpleType<Byte>(Byte.class); 95 96 /** 97 * The <code>SimpleType</code> instance describing values whose 98 * Java class name is <code>java.lang.Short</code>. 99 */ 100 public static final SimpleType<Short> SHORT = 101 new SimpleType<Short>(Short.class); 102 103 /** 104 * The <code>SimpleType</code> instance describing values whose 105 * Java class name is <code>java.lang.Integer</code>. 106 */ 107 public static final SimpleType<Integer> INTEGER = 108 new SimpleType<Integer>(Integer.class); 109 110 /** 111 * The <code>SimpleType</code> instance describing values whose 112 * Java class name is <code>java.lang.Long</code>. 113 */ 114 public static final SimpleType<Long> LONG = 115 new SimpleType<Long>(Long.class); 116 117 /** 118 * The <code>SimpleType</code> instance describing values whose 119 * Java class name is <code>java.lang.Float</code>. 120 */ 121 public static final SimpleType<Float> FLOAT = 122 new SimpleType<Float>(Float.class); 123 124 /** 125 * The <code>SimpleType</code> instance describing values whose 126 * Java class name is <code>java.lang.Double</code>. 127 */ 128 public static final SimpleType<Double> DOUBLE = 129 new SimpleType<Double>(Double.class); 130 131 /** 132 * The <code>SimpleType</code> instance describing values whose 133 * Java class name is <code>java.lang.String</code>. 134 */ 135 public static final SimpleType<String> STRING = 136 new SimpleType<String>(String.class); 137 138 /** 139 * The <code>SimpleType</code> instance describing values whose 140 * Java class name is <code>java.math.BigDecimal</code>. 141 */ 142 public static final SimpleType<BigDecimal> BIGDECIMAL = 143 new SimpleType<BigDecimal>(BigDecimal.class); 144 145 /** 146 * The <code>SimpleType</code> instance describing values whose 147 * Java class name is <code>java.math.BigInteger</code>. 148 */ 149 public static final SimpleType<BigInteger> BIGINTEGER = 150 new SimpleType<BigInteger>(BigInteger.class); 151 152 /** 153 * The <code>SimpleType</code> instance describing values whose 154 * Java class name is <code>java.util.Date</code>. 155 */ 156 public static final SimpleType<Date> DATE = 157 new SimpleType<Date>(Date.class); 158 159 /** 160 * The <code>SimpleType</code> instance describing values whose 161 * Java class name is <code>javax.management.ObjectName</code>. 162 */ 163 public static final SimpleType<ObjectName> OBJECTNAME = 164 new SimpleType<ObjectName>(ObjectName.class); 165 166 private static final SimpleType<?>[] typeArray = { 167 VOID, BOOLEAN, CHARACTER, BYTE, SHORT, INTEGER, LONG, FLOAT, 168 DOUBLE, STRING, BIGDECIMAL, BIGINTEGER, DATE, OBJECTNAME, 169 }; 170 171 172 private transient Integer myHashCode = null; // As this instance is immutable, these two values 173 private transient String myToString = null; // need only be calculated once. 174 175 176 /* *** Constructor *** */ 177 178 private SimpleType(Class<T> valueClass) { 179 super(valueClass.getName(), valueClass.getName(), valueClass.getName(), 180 false); 181 } 182 183 184 /* *** SimpleType specific information methods *** */ 185 186 /** 187 * Tests whether <var>obj</var> is a value for this 188 * <code>SimpleType</code> instance. <p> This method returns 189 * <code>true</code> if and only if <var>obj</var> is not null and 190 * <var>obj</var>'s class name is the same as the className field 191 * defined for this <code>SimpleType</code> instance (ie the class 192 * name returned by the {@link OpenType#getClassName() 193 * getClassName} method). 194 * 195 * @param obj the object to be tested. 196 * 197 * @return <code>true</code> if <var>obj</var> is a value for this 198 * <code>SimpleType</code> instance. 199 */ 200 public boolean isValue(Object obj) { 201 202 // if obj is null, return false 203 // 204 if (obj == null) { 205 return false; 206 } 207 208 // Test if obj's class name is the same as for this instance 209 // 210 return this.getClassName().equals(obj.getClass().getName()); 211 } 212 213 214 /* *** Methods overriden from class Object *** */ 215 216 /** 217 * Compares the specified <code>obj</code> parameter with this <code>SimpleType</code> instance for equality. 218 * <p> 219 * Two <code>SimpleType</code> instances are equal if and only if their 220 * {@link OpenType#getClassName() getClassName} methods return the same value. 221 * 222 * @param obj the object to be compared for equality with this <code>SimpleType</code> instance; 223 * if <var>obj</var> is <code>null</code> or is not an instance of the class <code>SimpleType</code>, 224 * <code>equals</code> returns <code>false</code>. 225 * 226 * @return <code>true</code> if the specified object is equal to this <code>SimpleType</code> instance. 227 */ 228 public boolean equals(Object obj) { 229 230 /* If it weren't for readReplace(), we could replace this method 231 with just: 232 return (this == obj); 233 */ 234 235 if (!(obj instanceof SimpleType<?>)) 236 return false; 237 238 SimpleType<?> other = (SimpleType<?>) obj; 239 240 // Test if other's className field is the same as for this instance 241 // 242 return this.getClassName().equals(other.getClassName()); 243 } 244 245 /** 246 * Returns the hash code value for this <code>SimpleType</code> instance. 247 * The hash code of a <code>SimpleType</code> instance is the the hash code of 248 * the string value returned by the {@link OpenType#getClassName() getClassName} method. 249 * <p> 250 * As <code>SimpleType</code> instances are immutable, the hash code for this instance is calculated once, 251 * on the first call to <code>hashCode</code>, and then the same value is returned for subsequent calls. 252 * 253 * @return the hash code value for this <code>SimpleType</code> instance 254 */ 255 public int hashCode() { 256 257 // Calculate the hash code value if it has not yet been done (ie 1st call to hashCode()) 258 // 259 if (myHashCode == null) { 260 myHashCode = Integer.valueOf(this.getClassName().hashCode()); 261 } 262 263 // return always the same hash code for this instance (immutable) 264 // 265 return myHashCode.intValue(); 266 } 267 268 /** 269 * Returns a string representation of this <code>SimpleType</code> instance. 270 * <p> 271 * The string representation consists of 272 * the name of this class (ie <code>javax.management.openmbean.SimpleType</code>) and the type name 273 * for this instance (which is the java class name of the values this <code>SimpleType</code> instance represents). 274 * <p> 275 * As <code>SimpleType</code> instances are immutable, the string representation for this instance is calculated once, 276 * on the first call to <code>toString</code>, and then the same value is returned for subsequent calls. 277 * 278 * @return a string representation of this <code>SimpleType</code> instance 279 */ 280 public String toString() { 281 282 // Calculate the string representation if it has not yet been done (ie 1st call to toString()) 283 // 284 if (myToString == null) { 285 myToString = this.getClass().getName()+ "(name="+ getTypeName() +")"; 286 } 287 288 // return always the same string representation for this instance (immutable) 289 // 290 return myToString; 291 } 292 293 private static final Map<SimpleType<?>,SimpleType<?>> canonicalTypes = 294 new HashMap<SimpleType<?>,SimpleType<?>>(); 295 static { 296 for (int i = 0; i < typeArray.length; i++) { 297 final SimpleType<?> type = typeArray[i]; 298 canonicalTypes.put(type, type); 299 } 300 } 301 302 /** 303 * Replace an object read from an {@link 304 * java.io.ObjectInputStream} with the unique instance for that 305 * value. 306 * 307 * @return the replacement object. 308 * 309 * @exception ObjectStreamException if the read object cannot be 310 * resolved. 311 */ 312 public Object readResolve() throws ObjectStreamException { 313 final SimpleType<?> canonical = canonicalTypes.get(this); 314 if (canonical == null) { 315 // Should not happen 316 throw new InvalidObjectException("Invalid SimpleType: " + this); 317 } 318 return canonical; 319 } 320 }